home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / database / io.c < prev    next >
Text File  |  1984-05-21  |  11KB  |  399 lines

  1. /* SDB - relation file I/O routines */
  2.  
  3. #include "stdio.h"
  4. #include "sdbio.h"
  5.  
  6. /* global error code variable */
  7. int dbv_errcode;
  8.  
  9. /* list of currently loaded relation definitions */
  10. static struct relation *relations = NULL;
  11.  
  12. /* rfind - find the specified relation */
  13. static struct relation *rfind(rname)
  14.   char *rname;
  15. {
  16.     int fd;
  17.     char filename[RNSIZE+5];
  18.     struct relation *rptr;
  19.  
  20.     /* look for relation in list currently loaded */
  21.     for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
  22.         if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
  23.             return (rptr);
  24.  
  25.     /* create a file name */
  26.     make_fname(filename,rname);
  27.  
  28.     /* lookup the relation file */
  29. #ifdef Lattice
  30.     if ((fd = open(filename,0x8000)) == -1)  /*NAs*/
  31. #else
  32.     if ((fd = open(filename,0)) == -1)
  33. #endif
  34.         return (db_nerror(RELFNF));
  35.  
  36.     /* allocate a new relation structure */
  37.     if ((rptr = malloc(sizeof(struct relation))) == NULL) {
  38.         close(fd);
  39.         return (db_nerror(INSMEM));
  40.     }
  41.  
  42.     /* initialize the relation structure */
  43.     rptr->rl_scnref = 0;
  44.  
  45.     /* read the header block */
  46.     if ( read(fd,&rptr->rl_header,512) != 512) {
  47.         free(rptr);
  48.         close(fd);
  49.         return (db_nerror(BADHDR));
  50.     }
  51.  
  52.     /* close the relation file */
  53.     close(fd);
  54.  
  55.     /* extract header information */
  56.     rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
  57.     rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
  58.     rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
  59.     rptr->rl_size = db_cvword(rptr->rl_header.hd_size);
  60.  
  61.     /* store the relation name */
  62.     stccpy(rptr->rl_name,rname,RNSIZE);
  63.  
  64.     /* link new relation into relation list */
  65.     rptr->rl_next = relations;
  66.     relations = rptr;
  67.  
  68.     /* return the new relation structure pointer */
  69.     return (rptr);
  70. }
  71.  
  72. /* db_ropen - open a relation file */
  73. struct scan *db_ropen(rname)
  74.   char *rname;
  75. {
  76.     struct relation *rptr;
  77.     struct scan *sptr;
  78.     char filename[RNSIZE+5];
  79.  
  80.     /* find the relation definition */
  81.     if ((rptr = rfind(rname)) == NULL)
  82.         return (NULL);
  83.  
  84.     /* allocate a new scan structure */
  85.     if ((sptr = malloc(sizeof(struct scan))) == NULL)
  86.         return (db_nerror(INSMEM));
  87.  
  88.     /* allocate a tuple buffer */
  89.     if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
  90.         free(sptr);
  91.         return (db_nerror(INSMEM));
  92.     }
  93.  
  94.     /* initialize the scan structure */
  95.     sptr->sc_relation = rptr;           /* store the relation struct addrs */
  96.     sptr->sc_dtnum = 0;                 /* desired tuple (non-existant) */
  97.     sptr->sc_atnum = 0;                 /* actual tuple (non-existant) */
  98.     sptr->sc_store = FALSE;             /* no store done since open */
  99.  
  100.     /* open relation file if necessary */
  101.     if (rptr->rl_scnref++ == 0) {
  102.  
  103.         /* create the relation file name */
  104.         make_fname(filename,rname);
  105.  
  106.         /* open the relation file */
  107. #ifdef Lattice
  108.         if ((rptr->rl_fd = open(filename,0x8002)) == -1) {  /*dns*/
  109. #else
  110.         if ((rptr->rl_fd = open(filename,2)) == -1) {
  111. #endif
  112.             rptr->rl_scnref--;
  113.             free(sptr->sc_tuple); free(sptr);
  114.             return (db_nerror(RELFNF));
  115.         }
  116.     }
  117.  
  118.     /* return the new scan structure pointer */
  119.     return (sptr);
  120. }
  121.  
  122. /* db_rclose - close the relation file */
  123. int db_rclose(sptr)
  124.   struct scan *sptr;
  125. {
  126.     struct relation *rptr,*lastrptr;
  127.  
  128.     /* close relation file if this is the last reference */
  129.     if (--sptr->sc_relation->rl_scnref == 0) {
  130.  
  131.         /* rewrite header if any stores took place */
  132.         if (sptr->sc_store) {
  133.  
  134.             /* store the tuple count back in the header */
  135.             db_cvbytes(sptr->sc_relation->rl_tcnt,
  136.                        sptr->sc_relation->rl_header.hd_tcnt);
  137.  
  138.             /* write the header block */
  139.             lseek(sptr->sc_relation->rl_fd,0L,0);
  140.             if (write(sptr->sc_relation->rl_fd,
  141.                       &sptr->sc_relation->rl_header,512) != 512) {
  142.                 close(sptr->sc_relation->rl_fd);
  143.                 free(sptr->sc_tuple); free(sptr);
  144.                 return (db_ferror(BADHDR));
  145.             }
  146.         }
  147.  
  148.         /* close the relation file */
  149.         close(sptr->sc_relation->rl_fd);
  150.  
  151.         /* free the relation header */
  152.         lastrptr = NULL;
  153.         for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
  154.             if (rptr == sptr->sc_relation) {
  155.                 if (lastrptr == NULL)
  156.                     relations = rptr->rl_next;
  157.                 else
  158.                     lastrptr->rl_next = rptr->rl_next;
  159.             }
  160.             lastrptr = rptr;
  161.         }
  162.         free(sptr->sc_relation);
  163.     }
  164.  
  165.     /* free the scan structure */
  166.     free(sptr->sc_tuple); free(sptr);
  167.  
  168.     /* return successfully */
  169.     return (TRUE);
  170. }
  171.  
  172. /* db_rcompress - compress a relation file */
  173. int db_rcompress(sptr)
  174.   struct scan *sptr;
  175. {
  176.     unsigned int next,nextfree,tcnt;
  177.  
  178.     /* get the last used tuple */
  179.     tcnt = sptr->sc_relation->rl_tcnt;
  180.  
  181.     /* loop through all of the tuples */
  182.     for (next = nextfree = 1; next <= tcnt; next++) {
  183.  
  184.         /* read the tuple */
  185.         seek(sptr,next);
  186.         if (read(sptr->sc_relation->rl_fd,
  187.                  sptr->sc_tuple,sptr->sc_relation->rl_size)
  188.                         != sptr->sc_relation->rl_size)
  189.             return (db_ferror(TUPINP));
  190.  
  191.         /* rewrite the tuple if it is active */
  192.         if (sptr->sc_tuple[0] == ACTIVE) {
  193.  
  194.             /* rewrite it only if it must move */
  195.             if (next != nextfree) {
  196.  
  197.                 /* write the tuple */
  198.                 seek(sptr,nextfree);
  199.                 if (write(sptr->sc_relation->rl_fd,
  200.                           sptr->sc_tuple,sptr->sc_relation->rl_size)
  201.                                 != sptr->sc_relation->rl_size)
  202.                     return (db_ferror(TUPOUT));
  203.             }
  204.  
  205.             /* update the next free tuple number */
  206.             nextfree += 1;
  207.         }
  208.     }
  209.  
  210.     /* update the tuple count */
  211.     sptr->sc_relation->rl_tcnt = nextfree - 1;
  212.  
  213.     /* remember which tuple is in the buffer */
  214.     sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
  215.  
  216.     /* reset the desired tuple */
  217.     sptr->sc_dtnum = 0;
  218.  
  219.     /* remember that the index needs rewriting */
  220.     sptr->sc_store = TRUE;
  221.  
  222.     /* return successfully */
  223.     return (TRUE);
  224. }
  225.  
  226. /* db_rbegin - begin scan at first tuple in relation */
  227. db_rbegin(sptr)
  228.   struct scan *sptr;
  229. {
  230.     /* begin with the first tuple in the file */
  231.     sptr->sc_dtnum = 0;
  232. }
  233.  
  234. /* db_rfetch - fetch the next tuple from the relation file */
  235. int db_rfetch(sptr)
  236.   struct scan *sptr;
  237. {
  238.     /* look for an active tuple */
  239.     while (TRUE) {
  240.  
  241.         /* check for this being the last tuple */
  242.         if (!db_rget(sptr,sptr->sc_dtnum + 1))
  243.             return (FALSE);
  244.  
  245.         /* increment the tuple number */
  246.         sptr->sc_dtnum += 1;
  247.  
  248.         /* return if the tuple found is active */
  249.         if (sptr->sc_tuple[0] == ACTIVE)
  250.             return (TRUE);
  251.     }
  252. }
  253.  
  254. /* db_rupdate - update the current tuple */
  255. int db_rupdate(sptr)
  256.   struct scan *sptr;
  257. {
  258.     /* make sure the status byte indicates an active tuple */
  259.     sptr->sc_tuple[0] = ACTIVE;
  260.  
  261.     /* write the tuple */
  262.     return (db_rput(sptr,sptr->sc_atnum));
  263. }
  264.  
  265. /* db_rdelete - delete the current tuple */
  266. int db_rdelete(sptr)
  267.   struct scan *sptr;
  268. {
  269.     /* make sure the status byte indicates a deleted tuple */
  270.     sptr->sc_tuple[0] = DELETED;
  271.  
  272.     /* write the tuple */
  273.     return (db_rput(sptr,sptr->sc_atnum));
  274. }
  275.  
  276. /* db_rstore - store a new tuple */
  277. int db_rstore(sptr)
  278.   struct scan *sptr;
  279. {
  280.     /* make sure there's room for this tuple */
  281.     if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
  282.         return (db_ferror(RELFUL));
  283.  
  284.     /* make sure the status byte indicates an active tuple */
  285.     sptr->sc_tuple[0] = ACTIVE;
  286.  
  287.     /* write the tuple */
  288.     if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
  289.         return (FALSE);
  290.  
  291.     /* update the tuple count */
  292.     sptr->sc_relation->rl_tcnt += 1;
  293.  
  294.     /* remember that a tuple was stored */
  295.     sptr->sc_store = TRUE;
  296.  
  297.     /* return successfully */
  298.     return (TRUE);
  299. }
  300.  
  301. /* db_rget - get a tuple from the relation file */
  302. int db_rget(sptr,tnum)
  303.   struct scan *sptr; unsigned int tnum;
  304. {
  305.     /* check to see if the tuple is already in the buffer */
  306.     if (tnum == sptr->sc_atnum)
  307.         return (TRUE);
  308.  
  309.     /* check for this being beyond the last tuple */
  310.     if (tnum > sptr->sc_relation->rl_tcnt)
  311.         return (db_ferror(TUPINP));
  312.  
  313.     /* read the tuple */
  314.     seek(sptr,tnum);
  315.     if (read(sptr->sc_relation->rl_fd,
  316.              sptr->sc_tuple,sptr->sc_relation->rl_size)
  317.                 != sptr->sc_relation->rl_size)
  318.         return (db_ferror(TUPINP));
  319.  
  320.     /* remember which tuple is in the buffer */
  321.     sptr->sc_atnum = tnum;
  322.  
  323.     /* return successfully */
  324.     return (TRUE);
  325. }
  326.  
  327. /* db_rput - put a tuple to a relation file */
  328. int db_rput(sptr,tnum)
  329.   struct scan *sptr; unsigned int tnum;
  330. {
  331.     /* check for this being beyond the maximum tuple */
  332.     if (tnum > sptr->sc_relation->rl_tmax)
  333.         return (db_ferror(TUPOUT));
  334.  
  335.     /* write the tuple */
  336.     seek(sptr,tnum);
  337.     if (write(sptr->sc_relation->rl_fd,
  338.               sptr->sc_tuple,sptr->sc_relation->rl_size)
  339.                 != sptr->sc_relation->rl_size)
  340.         return (db_ferror(TUPOUT));
  341.  
  342.     /* remember which tuple is in the buffer */
  343.     sptr->sc_atnum = tnum;
  344.  
  345.     /* return successfully */
  346.     return (TRUE);
  347. }
  348.  
  349. /* seek - seek a tuple in a relation file */
  350. static seek(sptr,tnum)
  351.   struct scan *sptr; unsigned int tnum;
  352. {
  353.     long offset;
  354.  
  355.     offset = (long) sptr->sc_relation->rl_data +
  356.                 ((long) (tnum - 1) * (long) sptr->sc_relation->rl_size);
  357.     lseek(sptr->sc_relation->rl_fd,offset,0);
  358. }
  359.  
  360. /* make_fname - make a relation name into a file name */
  361. static make_fname(fname,rname)
  362.   char *fname,*rname;
  363. {
  364.     stccpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
  365.     strcat(fname,".sdb");
  366. }
  367.  
  368. /* db_nerror - store the error code and return NULL */
  369. int db_nerror(errcode)
  370.   int errcode;
  371. {
  372.     dbv_errcode = errcode;
  373.     return (NULL);
  374. }
  375.  
  376. /* db_ferror - store the error code and return FALSE */
  377. int db_ferror(errcode)
  378.   int errcode;
  379. {
  380.     dbv_errcode = errcode;
  381.     return (FALSE);
  382. }
  383.  
  384. /* db_cvword - convert 2 bytes to a word */
  385. int db_cvword(bytes)
  386.   char bytes[2];
  387. {
  388.     return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
  389. }
  390.  
  391. /* db_cvbytes - convert a word to 2 bytes */
  392. db_cvbytes(word,bytes)
  393.   int word; char bytes[2];
  394. {
  395.     bytes[0] = word;
  396.     bytes[1] = word >> 8;
  397. }
  398.  
  399.